package com.unbox.common.util;

import com.unbox.common.configuration.message.UnBoxMessageUtils;
import com.unbox.common.configuration.redis.UnboxCache;
import com.unbox.common.configuration.redisson.DistributedLocker;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class UnBoxUtils {
    static DistributedLocker distributedLocker;
    static UnBoxMessageUtils unBoxMessageUtils;
    static RedisTemplate redisTemplate;

    public static void setDistributedLocker(DistributedLocker distributedLocker) {
        UnBoxUtils.distributedLocker = distributedLocker;
    }

    public static void setUnBoxMessageUtils(UnBoxMessageUtils unBoxMessageUtils) {
        UnBoxUtils.unBoxMessageUtils = unBoxMessageUtils;
    }

    public static void setCacheClient(Object client) {
        redisTemplate = (RedisTemplate) client;
    }

    /**
     * 缓存工具包 redis 实现 以后可以扩展部分缓存功能增加多缓存 等等场景
     */
    public static class Cache implements UnboxCache {
        @Override
        public Object get(Object key) {
            return redisTemplate.opsForValue().get(key);
        }

        @Override
        public void set(Object key, String value) {
            redisTemplate.opsForValue().set(key, value);
        }

        @Override
        public void set(Object key, String value, int time) {
            redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
        }

        @Override
        public boolean hasKey(Object key) {
            return redisTemplate.hasKey(key);
        }

        @Override
        public boolean delete(Object key) {
            redisTemplate.delete(key);
            return true;
        }

        @Override
        public boolean deleteBatch(Object key) {
            Set<String> keys = redisTemplate.keys(key);
            List<Object> values = redisTemplate.opsForValue().multiGet(keys);
            redisTemplate.delete(values);
            return true;
        }
    }

    /**
     * 国际化日志输出
     */
    public static class LocaleMessageLog implements UnboxLog {
        private Logger logger = null;

        public LocaleMessageLog() {
            logger = LoggerFactory.getLogger(LocaleMessageLog.class);
        }

        public LocaleMessageLog(Class cls) {
            logger = LoggerFactory.getLogger(cls);
        }

        private String splicing(String... key) {
            String keyStr = key[0];
            String message = unBoxMessageUtils.get(keyStr);
            StringBuilder builder = new StringBuilder();
            builder.append(message);
            builder.append(" : keyAndError=");
            for(Object keys : key) {
               builder.append("  ");
               builder.append(keys);
            }
            return builder.toString();
        }

        @Override
        public Logger getLogger() {
            return logger;
        }

        /**
         * 根据国际化文件输出日志(传递多字符串参数 首位参数是key)
         * @param key
         */
        @Override
        public void info(String... key) {
            logger.info(splicing(key));
        }

        /**
         * 根据国际化文件输出日志(传递多字符串参数 首位参数是key)
         * @param key
         */
        @Override
        public void error(String... key) {
           logger.error(splicing(key));
        }

        /**
         * 根据国际化文件输出日志(传递多字符串参数 首位参数是key)
         * @param key
         */
        @Override
        public void debug(String... key) {
            logger.debug(splicing(key));
        }

        /**
         * 根据国际化文件输出日志(传递多字符串参数 首位参数是key)
         * @param key
         */
        @Override
        public void warning(String... key) {
            logger.warn(splicing(key));
        }
    }

    /**
     * 分布式锁实现
     */
    public static class Lock implements DistributedLocker{
        private static final Logger logger = LoggerFactory.getLogger(Lock.class);

        @Override
        public RLock lock(String lockKey) {
            return distributedLocker.lock(lockKey);
        }

        @Override
        public RLock lock(String lockKey, int timeout) {
            return distributedLocker.lock(lockKey, timeout);
        }

        @Override
        public RLock lock(String lockKey, TimeUnit unit, int timeout) {
            return distributedLocker.lock(lockKey, unit, timeout);
        }

        @Override
        public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
            return distributedLocker.tryLock(lockKey,unit,waitTime,leaseTime);
        }

        @Override
        public void unlock(String lockKey) {
            distributedLocker.unlock(lockKey);
        }

        @Override
        public void unlock(RLock lock) {
            distributedLocker.unlock(lock);
        }

        @Override
        public void setRedissonClient(RedissonClient redissonClient) {
            distributedLocker.setRedissonClient(redissonClient);
        }
    }
}
